home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir35 / csap421.zip / SORTDIR.C < prev    next >
C/C++ Source or Header  |  1994-02-25  |  10KB  |  404 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <conio.h>
  5. #include <dos.h>
  6. #include <ctype.h>
  7. #include <mem.h>
  8. #include <alloc.h>
  9.  
  10. #include "dosstruc.h"
  11.  
  12. /*---   Function Prototypes   ---*/
  13.  
  14. int             SearchFirst(struct ExtFcb * Fcb);
  15. int             AbortProgram(void);
  16. int             isdevice(int handle);
  17. void            ReadRoot(void);
  18. void            ReadSub(void);
  19. void            WriteRoot(void);
  20. void            WriteSub(void);
  21. long            Alu2Sec(struct DpbStruct * Dpb, unsigned Alu);
  22. char           *strrspn(char *s1, char *s2);
  23. void            PutQueue(struct ClusterQueue * Q, unsigned Cluster);
  24. unsigned        NextCl(int Is12Bit, unsigned Cluster);
  25. void            FreeCluster(int Is12Bit, unsigned Val, unsigned Cluster);
  26.  
  27. /*---  End of Prototypes  ---*/
  28.  
  29.  
  30. /*
  31.  * SORTDIR is the main routine of CSAP.  It is a recursive routine that will
  32.  * walk the directory hierarchy, sorting all directories that it finds.  It
  33.  * uses the quick sort or quicker sort algorithm provided by most C runtime
  34.  * libraries to perform the actual sort.  It uses DOS Int 25H and 26H,
  35.  * Absolute Disk Read and Absolute Disk Write, to read the directories into
  36.  * memory for sorting and to write out the sorted directories.  It depends
  37.  * upon information about the physical characteristics of the disk provided
  38.  * by GETDPB.
  39.  */
  40.  
  41. extern struct absr32m a32;
  42.  
  43.  void
  44. SortDir (void) {
  45.     extern char     Disk, Parent[67], Element[13];
  46.     extern char     Line[80], Level, RSwt, VerSwt, Packed, TruncateSwt;
  47.     extern int      Lim, j, l;
  48.     extern int      OutSectors, OutClusters, BytesPerCluster, ECount;
  49.     extern int     *CluArray;
  50.     extern unsigned NumSec;
  51.     extern unsigned DirStart;
  52.     extern long     MinMem;
  53.     extern struct DpbStruct Dpb;
  54.     extern struct DirEntry *DirBuff;
  55.     extern struct ClusterEntry *p, *t;
  56.     extern struct ExtFcb Fcb;
  57.     extern struct ExtendedEntry Dir;
  58.     extern struct ClusterQueue CluQ;
  59.  
  60.     char           *strrspn();
  61.     char          **DirVector, *r;
  62.     int             strincmp();
  63.     int             i, k, DirCount, Root;
  64.     long            Mem;
  65.  
  66.     BytesPerCluster = (Dpb.ClusterSize + 1) * Dpb.SectorSize;
  67.     if (strlen(Element) != 0) {    /* Sorting a sub-directory */
  68.         Root = 0;
  69.         bdosptr(0x3B, Parent, 0);    /* Set Current Directory */
  70.         if ((Parent[strlen(Parent) - 1] != '\\') && (Parent[strlen(Parent) - 1] != '/'))
  71.             strcat(Parent, "\\");
  72.         setdta((char *) &Dir);
  73.         parsfnm(Element, (struct fcb *) & Fcb.DriveId, 0);
  74.         Fcb.FcbHdr.Header = 0xFF;
  75.         Fcb.DriveId = Disk - '@';
  76.         Fcb.FcbHdr.Attrib = 0xFF;
  77.         if (SearchFirst(&Fcb) != 0) {
  78.             fprintf(stderr, "Not found: %s%s\n", Parent, Element);
  79.             AbortProgram();
  80.         }
  81.     }
  82.     else Root = 1;    /* Sorting the Root directory */
  83.  
  84.     printf("Sorting: %s%s", Parent, Element);
  85.     if (!isdevice(1)) fprintf(stderr, "Sorting: %s%s", Parent, Element);
  86.  
  87.     /* Read directory to be sorted into memory */
  88.  
  89.     if (Root) ReadRoot();
  90.     else ReadSub();
  91.  
  92.     /* Count sub-directories, skipping "current" and "parent" entries */
  93.  
  94.     for (DirCount = 0, i = 0; i < Lim / sizeof(struct DirEntry); i++) {
  95.         if (DirBuff[i].Name[0] == 0) break;
  96.         if ((DirBuff[i].Attribute & 0x10)
  97.             && (DirBuff[i].Name[0] != '.')
  98.             && (DirBuff[i].Name[0] != 0xE5)) DirCount++;
  99.     }
  100.     k = i;
  101.     if (DirCount != 0) {
  102.         if ((DirVector = malloc(DirCount * sizeof(DirVector))) == NULL) {
  103.             fprintf(stderr, "Insufficient memory (2).\n");
  104.             return;
  105.         }
  106.     }
  107.     j = 0;
  108.     if (Root) {
  109.  
  110.         /*
  111.          * If sorting Root - skip 1st two files if "System" &
  112.          * "Hidden"
  113.          */
  114.  
  115.         if (i > 1) {
  116.             if (DirBuff[j].Attribute & 0x06) {
  117.                 j++;
  118.                 i--;
  119.                 if (DirBuff[j].Attribute & 0x06) {
  120.                     j++;
  121.                     i--;
  122.                 }
  123.             }
  124.         }
  125.     }
  126.     else {
  127.  
  128.         /*
  129.          * If sorting subdirectory - skip 1st two entries, "current"
  130.          * and "parent"
  131.          */
  132.  
  133.         j += 2;
  134.         i -= 2;
  135.     }
  136.     if (i == 0) {
  137.         printf(" Empty.\n");
  138.         r = &Parent[strlen(Parent) - 1];
  139.         if (r[-1] == ':') r++;
  140.         *r = 0x00;
  141.         if (TruncateSwt) {
  142.             OutClusters = 1;
  143.             WriteSub();
  144.         }
  145.         return;
  146.     }
  147.  
  148.     /* If VerSwt ON - request operator confirmation BEFORE sorting */
  149.  
  150.     if (VerSwt != 0) {
  151.         if (isdevice(1)) {
  152.             printf("   Sort (Y or N)? ");
  153.             fflush(stdout);
  154.         }
  155.         else {
  156.             fprintf(stderr, "   Sort (Y or N)? ");
  157.             fflush(stderr);
  158.         }
  159.         if (toupper(getche()) != 'Y') {
  160.             if (!isdevice(1)) fprintf(stderr, "n");
  161.             printf("\n");
  162.             return;
  163.         }
  164.     }
  165.     if (!isdevice(1)) fprintf(stderr, "\n");
  166.     printf("\n");
  167.  
  168.     /* Sort directory */
  169.  
  170.     qsort(&DirBuff[j], i, sizeof(struct DirEntry), strincmp);
  171.  
  172.     ECount = 0;
  173.  
  174.     /*
  175.      * If Packed OFF, remove "erased" entries from directory (mark them
  176.      * "unused")
  177.      */
  178.  
  179.     if (Packed != 0) {
  180.         for (i = k; i >= 0; i--) {
  181.             if ((DirBuff[i].Name[0] != 0xE5) && (DirBuff[i].Name[0] != 0x00))
  182.                 break;
  183.             if (DirBuff[i].Name[0] == 0xE5) {
  184.                 memset(DirBuff[i].Name, '\0', sizeof(DirBuff[i]));
  185.                 ++ECount;
  186.             }
  187.         }
  188.         i = k;
  189.     }
  190.     if (TruncateSwt) {
  191.         for (i = k; i > 0; --i) {
  192.             if (DirBuff[i-1].Name[0] != 0x00) break;
  193.         }
  194.     }
  195.  
  196.     /*
  197.      * Compute the number of directory sectors to write out - don't write
  198.      * sectors that don't contain active entries.
  199.      */
  200.  
  201.     OutSectors = ((i * 32) + Dpb.SectorSize - 1) / Dpb.SectorSize;
  202.     OutClusters = (OutSectors + Dpb.ClusterSize) >> Dpb.ClusterShift;
  203.  
  204.     /*
  205.      * Build list of subdirectories - skipping "current" and "parent"
  206.      * entries
  207.      */
  208.  
  209.     for (l = 0, i = 0; DirBuff[i].Name[0]; i++) {
  210.         if ((DirBuff[i].Attribute & 0x10) && (DirBuff[i].Name[0] != '.')) {
  211.             for (k = 0, j = 0; j < 8; ++j) {
  212.                 if (DirBuff[i].Name[j] == ' ') break;
  213.                 else Line[k++] = DirBuff[i].Name[j];
  214.             }
  215.             if (DirBuff[i].Ext[0] != ' ') {
  216.                 Line[k++] = '.';
  217.                 for (j = 0; j < 3; ++j) {
  218.                     if (DirBuff[i].Ext[j] == ' ') break;
  219.                     else Line[k++] = DirBuff[i].Ext[j];
  220.                 }
  221.             }
  222.             Line[k++] = '\0';
  223.             if ((DirVector[l] = malloc(k)) == NULL) {
  224.                 fprintf(stderr, "Insufficient memory.\n");
  225.                 return;
  226.             }
  227.             strcpy(DirVector[l++], Line);
  228.         }
  229.     }
  230.  
  231.     /* Write out sorted directory */
  232.  
  233.     if (Root) {
  234.         WriteRoot();
  235.         if (RSwt)
  236.             printf("    Location: %04XH-%04XH\n", DirStart, DirStart + NumSec - 1);
  237.     }
  238.     else {
  239.         WriteSub();
  240.         if (RSwt) {
  241.             printf("    Location:");
  242.             for (i = 0; i < CluQ.Count; ++i) {
  243.                 if (i == 0) printf(" %04XH", Alu2Sec(&Dpb, CluArray[i]));
  244.                 if ((i > 0) && (CluArray[i] != CluArray[i - 1] + 1)) {
  245.                     printf("-%04XH %04XH",
  246.                            Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1,
  247.                            Alu2Sec(&Dpb, CluArray[i])
  248.                           );
  249.                 }
  250.             }
  251.             printf("-%04XH\n", Alu2Sec(&Dpb, CluArray[i - 1] + 1) - 1);
  252.         }
  253.     }
  254.     if (RSwt) printf("    %d Erased entries removed\n", ECount);
  255.  
  256.     Mem = coreleft();
  257.     if (MinMem < Mem) MinMem = Mem;
  258.  
  259.     /* Release dynamically acquired space for this directory */
  260.  
  261.     free(DirBuff);
  262.     for (p = CluQ.Head; p != NULL; p = t) {
  263.         t = p->Next;
  264.         free(p);
  265.     }
  266.     free(CluArray);
  267.  
  268.     /*
  269.      * If Recursive sort - build Parent and Element for sub directories &
  270.      * sort
  271.      */
  272.  
  273.     if (!Level) {
  274.         strcat(Parent, Element);
  275.         for (i = 0; i < DirCount; i++) {
  276.             strcpy(Element, DirVector[i]);
  277.  
  278.             SortDir();
  279.  
  280.         }
  281.         r = strrspn(Parent, "\\/");
  282.         if (r[-1] == ':') r++;
  283.         *r = 0x00;
  284.     }
  285. }
  286.  
  287.  void
  288. ReadSub (void) {
  289.     extern unsigned Cluster;
  290.     extern unsigned LastCluster;
  291.     extern struct ExtendedEntry Dir;
  292.     extern struct ClusterQueue CluQ;
  293.     extern int      Is12Bit, *CluArray, BytesPerCluster, Lim;
  294.     extern char     Disk;
  295.     extern struct DirEntry *DirBuff;
  296.     extern struct DpbStruct Dpb;
  297.  
  298.     int             i;
  299.     struct ClusterEntry *p;
  300.     void            PutQueue();
  301.     unsigned        NextCl();
  302.  
  303.     Cluster = Dir.Body.FirstCluster;
  304.     CluQ.Head = CluQ.Current = NULL;
  305.     CluQ.Count = 0;
  306.     while (Cluster < LastCluster) {
  307.         PutQueue(&CluQ, Cluster);
  308.         Cluster = NextCl(Is12Bit, Cluster);
  309.     }
  310.     if ((CluArray = malloc(CluQ.Count * sizeof(int))) == NULL) {
  311.         fprintf(stderr, "Insufficient memory (3).\n");
  312.         return;
  313.     }
  314.     for (i = 0, p = CluQ.Head; p != NULL; i++, p = p->Next) {
  315.         CluArray[i] = p->Cluster;
  316.     }
  317.     Lim = CluQ.Count * BytesPerCluster;
  318.     if ((DirBuff = malloc(Lim)) == NULL) {
  319.         fprintf(stderr, "Insufficient memory for directory buffer.\n");
  320.         return;
  321.     }
  322.     for (i = 0; i < CluQ.Count; i++) {
  323.          if (absread(Disk - 'A', Dpb.ClusterSize + 1, Alu2Sec(&Dpb,
  324.                      CluArray[i]), (char *) &DirBuff[(i * BytesPerCluster) /
  325.                      32])) {
  326.             fprintf(stderr, "Error reading directory.\n");
  327.             exit(1);
  328.         }
  329.     }
  330. }
  331.  
  332.  void
  333. WriteSub (void) {
  334.     extern char     TruncateSwt;
  335.     extern char     FatDirty;
  336.     extern struct ClusterQueue CluQ;
  337.     extern char     Disk;
  338.     extern struct DpbStruct Dpb;
  339.     extern int      Is12Bit, *CluArray, BytesPerCluster;
  340.     extern int      OutClusters;
  341.     extern struct DirEntry *DirBuff;
  342.  
  343.     int             i;
  344.  
  345.     for (i = 0; i < OutClusters; i++) {
  346.          if (abswrite(Disk - 'A', Dpb.ClusterSize + 1,
  347.                      Alu2Sec(&Dpb, CluArray[i]), (char *) &DirBuff[(i *
  348.                      BytesPerCluster) / 32])) {
  349.             fprintf(stderr, "Error writing directory.\n");
  350.             exit(1);
  351.         }
  352.     }
  353.     if ((TruncateSwt) && (i < CluQ.Count)) {
  354.         FatDirty |= 1;
  355.         FreeCluster(Is12Bit, 0xFFFF, CluArray[i - 1]);
  356.         for (; i < CluQ.Count; ++i)
  357.             FreeCluster(Is12Bit, 0, CluArray[i]);
  358.     }
  359. }
  360.  
  361.  void
  362. ReadRoot (void) {
  363.     extern struct DpbStruct Dpb;
  364.     extern unsigned NumSec;
  365.     extern unsigned DirStart;
  366.     extern struct DirEntry *DirBuff;
  367.     extern int     *CluArray, Lim;
  368.     extern char     Disk;
  369.  
  370.     int             Error;
  371.  
  372.     Lim = Dpb.MaxEntries * 32;
  373.     NumSec = (Lim + Dpb.SectorSize - 1) / Dpb.SectorSize;
  374.     if ((DirBuff = malloc(Lim)) == NULL) {
  375.         fprintf(stderr, "Insufficient memory for cluster buffer.\n");
  376.         return;
  377.     }
  378.     if ((CluArray = malloc(sizeof(int))) == NULL) {
  379.         fprintf(stderr, "Insufficient memory (4).\n");
  380.         return;
  381.     }
  382.     CluArray[0] = 0;
  383.  
  384.     if ((Error = absread(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) != 0) {
  385.         fprintf(stderr, "Error reading root:  %04X.\n", Error);
  386.         exit(1);
  387.     }
  388. }
  389.  
  390.  
  391.  void
  392. WriteRoot (void) {
  393.     extern char     Disk;
  394.     extern unsigned NumSec;
  395.     extern unsigned DirStart;
  396.     extern struct DpbStruct Dpb;
  397.     extern struct DirEntry *DirBuff;
  398.  
  399.     if (abswrite(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) {
  400.         fprintf(stderr, "Error writing Root.\n");
  401.         exit(1);
  402.     }
  403. }
  404.